package com.tbit.uqbike.webmanager.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tbit.uqbike.annos.OperateLog;
import com.tbit.uqbike.constant.RedisConstant;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.User;
import com.tbit.uqbike.object.pojo.dto.AddFaceDataDTO;
import com.tbit.uqbike.object.pojo.dto.UserFaceLogDTO;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.webmanager.business.userfacelog.object.UserFaceLog;
import com.tbit.uqbike.webmanager.business.userfacelog.object.vo.UserFaceLogVo;
import com.tbit.uqbike.object.pojo.vo.UserFaceDataVO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.business.UserFaceDataService;
import com.tbit.uqbike.service.business.UserService;
import com.tbit.uqbike.webmanager.business.userfacelog.service.UserFaceLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 人脸识别相关接口
 *
 * @author yee_
 * @version 1.0
 * @date 2023/5/5 15:15
 */
@RestController
@RequestMapping("/user/face")
public class UserFaceDataController {
    @Resource
    private UserFaceDataService userFaceDataService;
    @Resource
    private UserService userService;
    @Resource
    private UserFaceLogService userFaceLogService;
    @Resource
    private RedisService redisService;

    /**
     * 人脸识别缓存列表
     *
     * @param page
     * @param size
     * @param accountId
     * @param request
     * @param phone
     * @return
     */
    @GetMapping("/listPage")
    public Result<PageResult<UserFaceDataVO>> listPage(@RequestParam(required = false, defaultValue = "1") Integer page,
                                                       @RequestParam(required = false, defaultValue = "10") Integer size,
                                                       @RequestParam Integer accountId, HttpServletRequest request,
                                                       String phone) {
        LoginInfo login = BaseController.getLogin(request);
        if (Boolean.FALSE.equals(login.roleIsAdmin())) {
            throw new BaseException("仅允许超级管理员查看");
        }
        LambdaQueryWrapper<UserFaceDataVO> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(phone)) {
            User user = userService.getByAccountPhone(accountId, phone);
            if (user == null) {
                return Result.success(new PageResult<>(page, size, 0L, 0, Collections.emptyList()));
            }
            wrapper.eq(UserFaceDataVO::getUserId, user.getUserId());
        }
        wrapper.eq(UserFaceDataVO::getAccountId, accountId);
        wrapper.orderBy(true, false, UserFaceDataVO::getFaceId);
        Page<UserFaceDataVO> pageInfo = userFaceDataService.page(Page.of(page, size), wrapper);
        if (StringUtils.isNotBlank(phone)) {
            pageInfo.getRecords().forEach(x -> {
                x.setPhone(phone);
                x.formatSimilar();
            });
        } else {
            Set<Integer> userIdSet = pageInfo.getRecords().stream().map(UserFaceDataVO::getUserId).collect(Collectors.toSet());
            Map<Integer, User> userMap = userService.mapByUserIdAndAccountId(userIdSet, accountId);
            pageInfo.getRecords().forEach(x -> {
                x.setPhone(userMap.getOrDefault(x.getUserId(), new User()).getPhone());
                x.formatSimilar();
            });
        }
        return Result.success(new PageResult<>(page, size, pageInfo.getTotal(), (int) pageInfo.getPages(), pageInfo.getRecords()));
    }

    /**
     * 人脸识别记录
     *
     * @param name    用户姓名
     * @param phone   手机号
     * @param idNO    身份证号
     * @param success 是否认证成功
     */
    @GetMapping("/record/list")
    public Result<PageResult<UserFaceLogVo>> getLogList(@RequestParam(required = false, defaultValue = "1") Integer page,
                                                        @RequestParam(required = false, defaultValue = "10") Integer size,
                                                        @RequestParam Integer accountId,
                                                        HttpServletRequest request,
                                                        @RequestParam(required = false) String name,
                                                        @RequestParam(required = false) String phone,
                                                        @RequestParam(required = false) String idNO,
                                                        @RequestParam(required = false) Boolean success
    ) {
        LoginInfo login = BaseController.getLogin(request);
        if (Boolean.FALSE.equals(login.roleIsAdmin())) {
            throw new BaseException("仅允许超级管理员查看");
        }
        return Result.success(userFaceLogService.getRecordList(page, size, accountId, name, phone, idNO, success));
    }

    /**
     * 删除人脸缓存
     */
    @DeleteMapping("/delete/{faceId}")
    @OperateLog(module = ModuleEnum.USER_FACE_IDENTIFY, methods = MethodEnum.USER_FACE_IDENTIFY_DEL)
    public Result<String> delete(@PathVariable Integer faceId, HttpServletRequest request) {
        LoginInfo login = BaseController.getLogin(request);
        if (!login.roleIsAdmin()) {
            throw new BaseException("仅允许超级管理员操作");
        }
        UserFaceDataVO faceData = userFaceDataService.getById(faceId);
        userFaceDataService.removeById(faceId);

        // 清空人脸识别次数
        redisService.del(RedisConstant.FACE_CHECK + "_" + faceData.getUserId());

        return Result.success();
    }

    /**
     * 按用户id删除人脸缓存
     */
    @DeleteMapping("/deleteByUserId/{userId}")
    @OperateLog(module = ModuleEnum.USER_FACE_IDENTIFY, methods = MethodEnum.USER_FACE_IDENTIFY_DEL)
    public Result<String> deleteByUserId(@PathVariable Integer userId, HttpServletRequest request) {
        LoginInfo login = BaseController.getLogin(request);
//        if (!login.roleIsAdmin() && !login.roleIsFranchisee()) {
//            throw new BaseException("仅允许管理员或加盟商操作");
//        }

        userFaceDataService.remove(Wrappers.<UserFaceDataVO>query()
                .eq("userId", userId));

        // 清空人脸识别次数
        redisService.del(RedisConstant.FACE_CHECK + "_" + userId);

        return Result.success();
    }


    /**
     * 新增或修改人脸缓存
     * @param dto   dto
     * @param request   request
     * @return Result<Object>
     */
    @PostMapping("/addOrUpdateFace")
    @OperateLog(module = ModuleEnum.USER_FACE_IDENTIFY, methods = MethodEnum.USER_FACE_IDENTIFY_ADD)
    public Result<Object> addOrUpdateFace(@RequestBody @Valid AddFaceDataDTO dto, HttpServletRequest request) {
        LoginInfo login = BaseController.getLogin(request);
        if (Boolean.FALSE.equals(login.roleIsAdmin())) {
            throw new BaseException("仅允许超级管理员操作");
        }
        User user = userService.getByAccountPhone(dto.getAccountId(), dto.getPhone());
        if (Objects.isNull(user)) {
            return Result.error("用户不存在");
        }

        QueryWrapper<UserFaceDataVO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", user.getUserId());
        UserFaceDataVO userFaceDataVO = userFaceDataService.getOne(queryWrapper);

        if (Objects.isNull(userFaceDataVO)) {
            userFaceDataVO = new UserFaceDataVO();
        }
        userFaceDataVO
                .setUserId(user.getUserId())
                .setAccountId(dto.getAccountId())
                .setUrl(dto.getPhotoUrl())
                .setSimilarity(Objects.isNull(dto.getSimilarity()) ? 100D : dto.getSimilarity())
                .setAddTime(new Date())
                .setRemark("客服手动操作");
        userFaceDataService.saveOrUpdate(userFaceDataVO);
        return Result.success();
    }


    /**
     * 获取人脸详情
     * @param faceId 人脸ID
     * @param request   request
     * @return Result<UserFaceLog>
     */
    @GetMapping("/getFaceDetail")
    public Result<UserFaceLogVo> getFaceDetail(Integer faceId,  HttpServletRequest request){
        LoginInfo login = BaseController.getLogin(request);
        if (Boolean.FALSE.equals(login.roleIsAdmin())) {
            throw new BaseException("仅允许超级管理员查看");
        }
        if (Objects.isNull(faceId)){
            return Result.error("人脸ID不能为空");
        }
        return Result.success(userFaceLogService.getDetail(faceId));
    }


    /**
     * 更新人脸记录
     * @param dto dto
     * @param request request
     * @return  Result<Object>
     */
    @PostMapping("/updateFaceLog")
    @OperateLog(module = ModuleEnum.USER_FACE_IDENTIFY, methods = MethodEnum.USER_FACE_LOG_UPDATE)
    public Result<Object> updateFaceLog(@RequestBody @Valid UserFaceLogDTO dto, HttpServletRequest request) {
        LoginInfo login = BaseController.getLogin(request);
        if (Boolean.FALSE.equals(login.roleIsAdmin())) {
            throw new BaseException("仅允许超级管理员操作");
        }
        UserFaceLog userFaceLog = userFaceLogService.lambdaQuery()
                .eq(UserFaceLog::getFaceId, dto.getFaceId())
                .one();

        if (userFaceLog == null) {
            return Result.error("人脸记录不存在");
        }

        userFaceLog.setRemark("客服修改人脸记录");
        userFaceLog.setUrl(dto.getFaceUrl());

        boolean updated = userFaceLogService.updateById(userFaceLog);
        if (!updated) {
            return Result.error("人脸记录更新失败");
        }

        // 更新人脸缓存
        Integer userId = userFaceLog.getUserId();

        UserFaceDataVO userFaceDataVO = userFaceDataService.lambdaQuery()
                .eq(UserFaceDataVO::getUserId, userId)
                .one();

        if (userFaceDataVO == null) {
            userFaceDataVO = new UserFaceDataVO();
        }

        userFaceDataVO.setUserId(userId)
                .setAccountId(userFaceLog.getAccountId())
                .setUrl(dto.getFaceUrl())
                .setSimilarity(100D)
                .setAddTime(new Date())
                .setRemark("客服手动操作");

        boolean saved = userFaceDataService.saveOrUpdate(userFaceDataVO);
        if (!saved) {
            return Result.error("人脸缓存更新失败");
        }
        return Result.success();
    }

}
